home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / intrlib1.zip / INTR_BGI.C < prev    next >
C/C++ Source or Header  |  1992-03-10  |  38KB  |  1,072 lines

  1. /******************************************************************************
  2. * Low level graphics routines.                              *
  3. *                                          *
  4. *                    Written by Gershon Elber,  Oct. 1990  *
  5. *******************************************************************************
  6. * Supported device:                                  *
  7. * 1. CGA.                                      *
  8. * 2. EGA/VGA.                                      *
  9. * 3. Hercules.                                      *
  10. * 4. Super VGA.                                      *
  11. *******************************************************************************
  12. * History:                                      *
  13. *  15 Oct 90 - Version 1.0 by Gershon Elber.                      *
  14. ******************************************************************************/
  15.  
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <mem.h>
  20. #include <dos.h>
  21. #include <io.h>
  22. #include <graphics.h>
  23. #include <conio.h>
  24. #include <fcntl.h>
  25. #include <ctype.h>
  26. #include "intr_loc.h"
  27. #include "mousedrv.h"
  28. #include "intr_gr.h"
  29.  
  30. #define HISTORY_SIZE 10          /* History buffer length for GRGetGraphicLine. */
  31. #define GR_LINE_LEN    80      /* Maximum chars read by GRGetGraphicLine. */
  32.  
  33. #define SVGA_SPECIAL    999         /* User installed BGI Super VGA driver. */
  34.  
  35. #define    POINT_SIZE 0.05                  /* Size of + marker drawn. */
  36. #define    POINT_TITLE 0.02       /* Distance between point title and + marker. */
  37.  
  38. #define    CURSOR_IMAGE_X  24
  39. #define    CURSOR_IMAGE_Y  24
  40.  
  41. #define CURSOR_TYPE_STACK_SIZE 20     /* Size of stack to save cursor types. */
  42. #define VIEW_PORT_STACK_SIZE 20        /* Depth of view port setting stack. */
  43. #define TEXT_SETTING_STACK_SIZE 10         /* Depth of text setting stack. */
  44.  
  45. #define MAP_UP_X(x)  ((((x) - GRPanFactorX) << GRZoomFactor) + GRWidth2)
  46. #define MAP_UP_Y(y)  ((((y) - GRPanFactorY) << GRZoomFactor) + GRHeight2)
  47. #define MAP_DN_X(x)  ((((x) - GRPanFactorX) >> GRIZoomFactor) + GRWidth2)
  48. #define MAP_DN_Y(y)  ((((y) - GRPanFactorY) >> GRIZoomFactor) + GRHeight2)
  49. #define INVMAP_UP_X(x)  ((((x) - GRWidth2) >> GRZoomFactor) + GRPanFactorX)
  50. #define INVMAP_UP_Y(y)  ((((y) - GRHeight2) >> GRZoomFactor) + GRPanFactorY)
  51. #define INVMAP_DN_X(x)  ((((x) - GRWidth2) << GRIZoomFactor) + GRPanFactorX)
  52. #define INVMAP_DN_Y(y)  ((((y) - GRHeight2) << GRIZoomFactor) + GRPanFactorY)
  53.  
  54. int GRScreenMaxX, GRScreenMaxY;     /* The maximum resolution of the screen. */
  55. int GRScreenMaxColors;              /* The maximum # of colors available. */
  56. IntrRType GRScreenAspect = 1.0; /* Screen aspect ratio (pixel width/height). */
  57. int GRCurrentCursorX, GRCurrentCursorY;          /* Cursor current position. */
  58. int GRFontName, GRFontSize;         /* Global information on font used. */
  59. int GRDrawText;            /* If can not zoom down text, force draw. */
  60. int GRGraphMode = 0, GRGraphDriver = 0;       /* What driver/mode are we in. */
  61.  
  62. static int GRScreenMaxX2, GRScreenMaxY2;      /* Half of maximum resolution. */
  63. static VoidPtr GRPutImage = NULL;     /* If not null, used to save getimage. */
  64. static char *GRBGIDriverPath = "";       /* Where to look for BGI drivers. */
  65. static char *CursorImageBuffer;                    /* Cursor shape. */
  66. static int ScreenCursorColor;        /* Graphic and text (in graphic screen). */
  67. static int OldStdOut;    /* So we could recover it when exit from graph mode. */
  68. static int GRScreenGraphicMode;
  69. static char GRSVGAUserName[10];
  70. static int GRSVGAUserMode = 1;
  71. static int GRTextSize = 1;    /* Current text size: 1 = 8x8, 2 = 16x16 etc.. */
  72. static int GRWidth2 = 100;
  73. static int GRHeight2 = 100;
  74. static int GRMinX = 0;
  75. static int GRMinY = 0;
  76. static int GRZoomFactor = 0;
  77. static int GRIZoomFactor = 0;
  78. static int GRPanFactorX = 0;
  79. static int GRPanFactorY = 0;
  80. static struct text_info TextInfo;   /* So we can restore starting text mode. */
  81. static int ViewPortStackPtr = 0;
  82. static struct viewporttype far ViewPortStack[VIEW_PORT_STACK_SIZE];
  83. static int TextSettingStackPtr = 0;
  84. static struct textsettingstype TextSettingStack[TEXT_SETTING_STACK_SIZE];
  85. IntrInt2PtrFunc GlblGetChFunc = IntrGetEventWait;
  86.  
  87. static char HistoryBuffer[HISTORY_SIZE][GR_LINE_LEN + 1];
  88. static int HistoryBufLen = 0;
  89.  
  90. static int GRGetKey(void);
  91.  
  92. /****************************************************************************
  93. * Routine to be called for the user installed driver:                *
  94. ****************************************************************************/
  95. static int huge detectVGA(void)
  96. {
  97.     return GRSVGAUserMode;
  98. }
  99.  
  100. /****************************************************************************
  101. * Routine to install the Super VGA information.                    *
  102. * Note GraphDriver must be set to SVGA_SPECIAL for this to take affect.     *
  103. ****************************************************************************/
  104. void GRInstallSVGA(char *NameMode)
  105. {
  106.     char *p;
  107.  
  108.     p = strtok(NameMode, ".");
  109.     strcpy(GRSVGAUserName, p);
  110.  
  111.     p = strtok(NULL, ".");
  112.     sscanf(p, "%d", &GRSVGAUserMode);
  113.  
  114.     GRGraphDriver = SVGA_SPECIAL;
  115. }
  116.  
  117. /****************************************************************************
  118. * Routine to set the path to the BGI drivers location.                *
  119. ****************************************************************************/
  120. void GRSetBGIPath(char *BGIPath)
  121. {
  122.     GRBGIDriverPath = strdup(BGIPath);
  123. }
  124.  
  125. /****************************************************************************
  126. * Routine to set default driver (0 autodetect).                    *
  127. ****************************************************************************/
  128. void GRSetDefaultDriver(int GraphDriver)
  129. {
  130.     GRGraphDriver = GraphDriver;
  131. }
  132.  
  133. /****************************************************************************
  134. * Routine to reset all the system to starting condition    :            *
  135. ****************************************************************************/
  136. void GRInitGraph(void)
  137. {
  138.     int IsSVGA = FALSE;
  139.     int    i, j, GRScreenErrorCode;
  140.     unsigned char far
  141.         *BiosMode = (unsigned char far *) MK_FP(0x40, 0x49);
  142.  
  143.     if (GRScreenGraphicMode) return;
  144.     gettextinfo(&TextInfo);
  145.  
  146.     ViewPortStackPtr = 0;          /* Make sure view port stack is empty. */
  147.  
  148.     /* For some wierd reason, some machines waits much more than expected on */
  149.     /* the first delay. Lets do it now, so people will consider it part of   */
  150.     /* the initialization (make it a feature...)...                          */
  151.     delay(1);
  152.  
  153.     if (GRGraphDriver != SVGA_SPECIAL) {
  154.     if (GRGraphDriver == 0) {
  155.         /* Use autodetect feature of graphic library to see what we have.*/
  156.         detectgraph(&GRGraphDriver, &GRGraphMode);
  157.         if (GRGraphDriver < 0) {
  158.         IntrFatalError("Auto detect: No graphics device detected.");
  159.         }
  160.     }
  161.     }
  162.  
  163.     /* Put in the following any graphic driver specific setup: */
  164.     switch (GRGraphDriver) {
  165.     case CGA:
  166.         GRGraphMode = CGAHI;
  167.         break;
  168.     case ATT400:
  169.         GRGraphMode = ATT400HI;
  170.         break;
  171.     case EGA:
  172.         GRGraphMode = EGAHI;
  173.         break;
  174.     case EGA64:
  175.         GRGraphMode = EGA64HI;
  176.         break;
  177.     case EGAMONO:
  178.         GRGraphMode = EGAMONOHI;
  179.         break;
  180.     case HERCMONO:
  181.         GRGraphMode = HERCMONOHI;
  182.             /* Use 2nd page as aux mem! */
  183.         GRPutImage = (VoidPtr) MK_FP(0xb800, 0x0000);
  184.         break;
  185.     case VGA:
  186.         GRGraphMode = VGAHI;
  187.         break;
  188.     case SVGA_SPECIAL:
  189.         IsSVGA = TRUE;
  190.         installuserdriver(GRSVGAUserName, detectVGA);
  191.         GRGraphDriver = DETECT;
  192.         GRGraphMode = GRSVGAUserMode;
  193.         break;
  194.     default:
  195.         IntrFatalError("Requested graphic device is not supported");
  196.         break;
  197.     }
  198.  
  199.     initgraph(&GRGraphDriver, &GRGraphMode, GRBGIDriverPath);
  200.     if (IsSVGA)    GRGraphDriver = SVGA_SPECIAL;
  201.  
  202.     GRScreenErrorCode = graphresult();       /* Read result of initialization. */
  203.     if (GRScreenErrorCode != grOk) {           /* Error occured during init. */
  204.     IntrFatalError("Graphics System Error: can not intialize.");
  205.     }
  206.  
  207.     GRScreenMaxColors = getmaxcolor() + 1; /* Read maximum number of colors. */
  208.     ScreenCursorColor = (GRScreenMaxColors > 1 ? GRScreenMaxColors - 1 :
  209.                          GRScreenMaxColors);
  210.  
  211.     GRScreenMaxX = getmaxx();                 /* Read size of screen. */
  212.     GRScreenMaxY = getmaxy();
  213.     GRCurrentCursorX = GRScreenMaxX2 = GRScreenMaxX / 2;
  214.     GRCurrentCursorY = GRScreenMaxY2 = GRScreenMaxY / 2;
  215.     getaspectratio(&i, &j);            /* Read the hardware aspect. */
  216.     GRScreenAspect = ((IntrRType) i) / j;
  217.     setaspectratio(i, i);         /* Disable the aspect ratio affect. */
  218.  
  219.     GRFontName = DEFAULT_FONT;
  220.     GRFontSize = 1;
  221.  
  222.     /* Prepare the cursor (Arrow) image : */
  223.     cleardevice();
  224.     GRSetColor(ScreenCursorColor);
  225.     GRSetLineStyle(SOLID_LINE, 0, NORM_WIDTH);
  226.     GRSLine(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
  227.     j = CURSOR_IMAGE_X / 3;
  228.     for    (i = 1; i <= 7; i++) GRSLine(0, 0, j, j + i);/* Draw the arrow head. */
  229.     j = CURSOR_IMAGE_Y / 3;
  230.     for    (i = 1; i <= 7; i++) GRSLine(0, 0, j + i, j);
  231.  
  232.     CursorImageBuffer = _IntrMalloc(imagesize(0, 0, CURSOR_IMAGE_X,
  233.                             CURSOR_IMAGE_Y));
  234.     getimage(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y, CursorImageBuffer);
  235.  
  236.     GRClearAllScreen();
  237.  
  238.     GRSetSTextStyle(DEFAULT_FONT, HORIZ_DIR, 1);
  239.  
  240.     switch (GRGraphDriver) {
  241.         case CGA:
  242.         case ATT400:
  243.         case EGA:
  244.         case EGA64:
  245.         case EGAMONO:
  246.         case VGA:
  247.         MouseSetResolution(1000);
  248.         break;
  249.     case SVGA_SPECIAL:
  250.         MouseSetResolution(4000);
  251.         break;
  252.     case HERCMONO:
  253.         *BiosMode = 6;
  254.         /* Compensate on the text mode the mouse knows about as      */
  255.         /* hercules is not supported by the mouse driver!            */
  256.         MouseSetResolution(1000);
  257.         break;
  258.     }
  259.  
  260.     GRScreenGraphicMode = TRUE;
  261.     i = open("nul", O_WRONLY);      /* Redirect the stdout to nul: (no ^C...). */
  262.     fflush(stdout);
  263.     OldStdOut = dup(1);
  264.     dup2(i, 1);
  265.     close(i);
  266. }
  267.  
  268. /****************************************************************************
  269. * Routine to close and shutdown    graphic    mode :                    *
  270. ****************************************************************************/
  271. void GRCloseGraph(void)
  272. {
  273.     if (!GRScreenGraphicMode) return;
  274.     closegraph();              /* Return the system to text mode. */
  275.     GRScreenGraphicMode = FALSE;
  276.     dup2(OldStdOut, 1);            /* Recover stdout to its regular status. */
  277.     close(OldStdOut);
  278.  
  279.     textmode(TextInfo.currmode);
  280. }
  281.  
  282. /****************************************************************************
  283. * Routine to set line style parameters.                        *
  284. ****************************************************************************/
  285. void GRSetLineStyle(int LineStyle, unsigned int Pattern, int Thickness)
  286. {
  287.     setlinestyle(LineStyle, Pattern, Thickness);
  288. }
  289.  
  290. /****************************************************************************
  291. * Routine to set fill style parameters.                        *
  292. ****************************************************************************/
  293. void GRSetFillStyle(int Pattern, int Color)
  294. {
  295.     setfillstyle(Pattern, Color);
  296. }
  297.  
  298. /****************************************************************************
  299. * Routine to set write mode parameters.                        *
  300. ****************************************************************************/
  301. void GRSetWriteMode(int DrawMode)
  302. {
  303.     setwritemode(DrawMode);
  304. }
  305.  
  306. /****************************************************************************
  307. * Routine to set text horizontal and vertical justification.            *
  308. ****************************************************************************/
  309. void GRSetTextJustify(int HorizCenter, int VertCenter)
  310. {
  311.     settextjustify(HorizCenter, VertCenter);
  312. }
  313.  
  314. /****************************************************************************
  315. * Routine to set zoom factor for drawing.                    *
  316. *   Zoom factor of 0 means regular drawing while each inc/decremenet zooms  *
  317. * up/down respectively by a factor of 2.                    *
  318. ****************************************************************************/
  319. void GRSetZoomFactor(int ZoomFactor)
  320. {
  321.     GRZoomFactor = ZoomFactor;
  322.     GRIZoomFactor = -GRZoomFactor;
  323. }
  324.  
  325. /****************************************************************************
  326. * Routine to set pan factors for drawing space.                    *
  327. ****************************************************************************/
  328. void GRSetPanFactors(int PanFactorX, int PanFactorY)
  329. {
  330.     GRPanFactorX = PanFactorX;
  331.     GRPanFactorY = PanFactorY;
  332. }
  333.  
  334. /****************************************************************************
  335. * Routine to set text drawing parameters, in drawing space.            *
  336. ****************************************************************************/
  337. void GRSetTextStyle(int GRFontName, int Direction, int Size)
  338. {
  339.     GRTextSize = Size + GRZoomFactor;
  340.  
  341.     settextstyle(GRFontName, Direction, 1 << (MAX(GRTextSize, 1) - 1));
  342. }
  343.  
  344. /****************************************************************************
  345. * Routine to set text drawing parameters, in screen space.            *
  346. ****************************************************************************/
  347. void GRSetSTextStyle(int GRFontName, int Direction, int Size)
  348. {
  349.     settextstyle(GRFontName, Direction, Size);
  350. }
  351.  
  352. /****************************************************************************
  353. * Routine to set text drawing parameters.                    *
  354. ****************************************************************************/
  355. unsigned GRGetImageBufferSize(int x1, int y1, int x2, int y2)
  356. {
  357.     return imagesize(x1, y1, x2, y2);
  358. }
  359.  
  360. /****************************************************************************
  361. * Routine to set text drawing parameters.                    *
  362. ****************************************************************************/
  363. void GRGetImageBuffer(int x1, int y1, int x2, int y2, VoidPtr Buffer)
  364. {
  365.     getimage(x1, y1, x2, y2, Buffer);
  366. }
  367.  
  368. /****************************************************************************
  369. * Routine to set text drawing parameters.                    *
  370. ****************************************************************************/
  371. void GRPutImageBuffer(int x1, int y1, VoidPtr Buffer)
  372. {
  373.     putimage(x1, y1, Buffer, COPY_PUT);
  374. }
  375.  
  376. /****************************************************************************
  377. * Routine to XOR a rectangle area on screen using current color.        *
  378. ****************************************************************************/
  379. void GRXORRectangle(int x1, int y1, int x2, int y2)
  380. {
  381.     int i;
  382.     struct linesettingstype lineinfo;
  383.  
  384.     getlinesettings(&lineinfo);
  385.  
  386.     setwritemode(XOR_PUT);
  387.     setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
  388.  
  389.     for (i = y1; i <= y2; i++)
  390.     line(x1, i, x2, i);
  391.  
  392.     setwritemode(COPY_PUT);
  393.     setlinestyle(lineinfo.linestyle, lineinfo.upattern, lineinfo.thickness);
  394. }
  395.  
  396. /****************************************************************************
  397. * External reference for the mappings.                        *
  398. ****************************************************************************/
  399. int GRMapX(int x)
  400. {
  401.     return (GRZoomFactor > 0 ? MAP_UP_X(x) : MAP_DN_X(x)) + GRMinX;
  402. }
  403.  
  404. int GRMapY(int y)
  405. {
  406.     return (GRZoomFactor > 0 ? MAP_UP_Y(y) : MAP_DN_Y(y)) + GRMinY;
  407. }
  408.  
  409. /****************************************************************************
  410. * External reference for the inverse mapping.                        *
  411. ****************************************************************************/
  412. int GRInvMapX(int x)
  413. {
  414.     x -= GRMinX;
  415.     return (GRZoomFactor > 0 ? INVMAP_UP_X(x) : INVMAP_DN_X(x));
  416. }
  417.  
  418. int GRInvMapY(int y)
  419. {
  420.     y -= GRMinY;
  421.     return (GRZoomFactor > 0 ? INVMAP_UP_Y(y) : INVMAP_DN_Y(y));
  422. }
  423.  
  424. /****************************************************************************
  425. * Routine to draw a line, in Object spaces.                        *
  426. ****************************************************************************/
  427. void GRLine(int x1, int y1, int x2, int y2)
  428. {
  429.     if (GRZoomFactor > 0) {
  430.         moveto(MAP_UP_X(x1), MAP_UP_Y(y1));
  431.         lineto(MAP_UP_X(x2), MAP_UP_Y(y2));
  432.     }
  433.     else {
  434.         moveto(MAP_DN_X(x1), MAP_DN_Y(y1));
  435.         lineto(MAP_DN_X(x2), MAP_DN_Y(y2));
  436.     }
  437. }
  438.  
  439. /****************************************************************************
  440. * Routine to move to a new position, in Object space.                *
  441. ****************************************************************************/
  442. void GRMoveTo(int x, int y)
  443. {
  444.     if (GRZoomFactor > 0)
  445.         moveto(MAP_UP_X(x), MAP_UP_Y(y));
  446.     else
  447.         moveto(MAP_DN_X(x), MAP_DN_Y(y));
  448. }
  449.  
  450. /****************************************************************************
  451. * Routine to draw to a new position, in Object space.                *
  452. ****************************************************************************/
  453. void GRLineTo(int x, int y)
  454. {
  455.     if (GRZoomFactor > 0)
  456.         lineto(MAP_UP_X(x), MAP_UP_Y(y));
  457.     else
  458.         lineto(MAP_DN_X(x), MAP_DN_Y(y));
  459. }
  460.  
  461. /****************************************************************************
  462. * Routine to move to a new position, in Screen (pixels) space.            *
  463. ****************************************************************************/
  464. void GRSMoveTo(int x, int y)
  465. {
  466.     moveto(x, y);
  467. }
  468.  
  469. /****************************************************************************
  470. * Routine to draw to a new position, in Screen (pixels) space.            *
  471. ****************************************************************************/
  472. void GRSLineTo(int x, int y)
  473. {
  474.     lineto(x, y);
  475. }
  476.  
  477. /****************************************************************************
  478. * Routine to draw to a new position, in Screen (pixels) space.            *
  479. ****************************************************************************/
  480. void GRSLine(int x1, int y1, int x2, int y2)
  481. {
  482.     line(x1, y1, x2, y2);
  483. }
  484.  
  485. /****************************************************************************
  486. * Routine to move to a new position relative to current one, as in Object   *
  487. * space.                                    *
  488. ****************************************************************************/
  489. void GRMoveRel(int x, int y)
  490. {
  491.     if (GRZoomFactor > 0)
  492.     moverel(x << GRZoomFactor, y << GRZoomFactor);
  493.     else
  494.     moverel(x >> GRIZoomFactor, y >> GRIZoomFactor);
  495. }
  496.  
  497. /****************************************************************************
  498. * Routine to line to a new position relative to current one, as in Object   *
  499. * space.                                    *
  500. ****************************************************************************/
  501. void GRLineRel(int x, int y)
  502. {
  503.     if (GRZoomFactor > 0)
  504.     linerel(x << GRZoomFactor, y << GRZoomFactor);
  505.     else
  506.     linerel(x >> GRIZoomFactor, y >> GRIZoomFactor);
  507. }
  508.  
  509. /****************************************************************************
  510. * Routine to move to a new position relative to current one, as in Screen   *
  511. * space (pixel coords.).                            *
  512. ****************************************************************************/
  513. void GRSMoveRel(int x, int y)
  514. {
  515.     moverel(x, y);
  516. }
  517.  
  518. /****************************************************************************
  519. * Routine to line to a new position relative to current one, as in Screen   *
  520. * space (pixel coords.).                            *
  521. ****************************************************************************/
  522. void GRSLineRel(int x, int y)
  523. {
  524.     linerel(x, y);
  525. }
  526.  
  527. /****************************************************************************
  528. * Routine to draw a new polyline and fill it if Fill, in screen space.        *
  529. ****************************************************************************/
  530. void GRPoly(int n, int *Points, int Fill)
  531. {
  532.     int i, ii;
  533.  
  534.     if (GRZoomFactor > 0)
  535.         for (i = 0; i < n; i++) {
  536.         ii = i << 1;
  537.             Points[ii] = MAP_UP_X(Points[ii]);
  538.             Points[ii + 1] = MAP_UP_Y(Points[ii + 1]);
  539.      }
  540.     else
  541.         for (i = 0; i < n; i++) {
  542.         ii = i << 1;
  543.             Points[ii] = MAP_DN_X(Points[ii]);
  544.             Points[ii + 1] = MAP_DN_Y(Points[ii + 1]);
  545.      }
  546.  
  547.     if (Fill) {
  548.     /* There is a problem with BLACK color that fillpoly sometime does   */
  549.     /* not clear the border properly, so we need to redo it by drawpoly. */
  550.     fillpoly(n, Points);
  551.     drawpoly(n, Points);
  552.     }
  553.     else
  554.     drawpoly(n, Points);
  555. }
  556.  
  557. /****************************************************************************
  558. * Routine to draw a bar, in drawing space.                    *
  559. ****************************************************************************/
  560. void GRBar(int x1, int y1, int x2, int y2)
  561. {
  562.     if (GRZoomFactor > 0)
  563.     bar(MAP_UP_X(x1), MAP_UP_Y(y1), MAP_UP_X(x2), MAP_UP_Y(y2));
  564.     else
  565.     bar(MAP_DN_X(x1), MAP_DN_Y(y1), MAP_DN_X(x2), MAP_DN_Y(y2));
  566. }
  567.  
  568. /****************************************************************************
  569. * Routine to draw a bar, in screen space.                    *
  570. ****************************************************************************/
  571. void GRSBar(int x1, int y1, int x2, int y2)
  572. {
  573.     bar(x1, y1, x2, y2);
  574. }
  575.  
  576. /****************************************************************************
  577. * Routine to draw a circle, in drawing space.                    *
  578. ****************************************************************************/
  579. void GRCircle(int x, int y, int r)
  580. {
  581.     if (GRZoomFactor > 0)
  582.     circle(MAP_UP_X(x), MAP_UP_Y(y), r << GRZoomFactor);
  583.     else
  584.     circle(MAP_DN_X(x), MAP_DN_Y(y), r >> GRIZoomFactor);
  585. }
  586.  
  587. /****************************************************************************
  588. * Routine to draw an arc, in drawing space.                    *
  589. * As the Y axes is inverted the Angles should be inverted as well.        *
  590. ****************************************************************************/
  591. void GRArc(int x, int y, int StAngle, int EndAngle, int r)
  592. {
  593.     if (GRZoomFactor > 0)
  594.     arc(MAP_UP_X(x), MAP_UP_Y(y), -EndAngle, -StAngle, r << GRZoomFactor);
  595.     else
  596.     arc(MAP_DN_X(x), MAP_DN_Y(y), -EndAngle, -StAngle, r >> GRIZoomFactor);
  597. }
  598.  
  599. /****************************************************************************
  600. * Routine to draw the given text in given drawing space coordinates.        *
  601. ****************************************************************************/
  602. IntrBType GRDrawingText(void)
  603. {
  604.     return GRTextSize > 0 || GRDrawText;
  605. }
  606.  
  607. /****************************************************************************
  608. * Routine to draw the given text in given drawing space coordinates.        *
  609. ****************************************************************************/
  610. void GRText(int x, int y, char *s)
  611. {
  612.     /* If text can not be zoom down and we are not forced to draw - dont. */
  613.     if (GRTextSize < 1 && !GRDrawText) return;
  614.  
  615.     if (GRZoomFactor > 0)
  616.         outtextxy(MAP_UP_X(x), MAP_UP_Y(y), s);
  617.     else
  618.         outtextxy(MAP_DN_X(x), MAP_DN_Y(y), s);
  619. }
  620.  
  621. /****************************************************************************
  622. * Routine to draw the given text in given screen space coordinates.        *
  623. ****************************************************************************/
  624. void GRSText(int x, int y, char *s)
  625. {
  626.     outtextxy(x, y, s);
  627. }
  628.  
  629. /****************************************************************************
  630. * Routine to draw the given text in given screen space coordinates.        *
  631. * A Black shadow is drawn for the given string.                    *
  632. ****************************************************************************/
  633. void GRSTextShadow(int x, int y, int Color, char *s)
  634. {
  635.     GRSetColor(BLACK);
  636.     outtextxy(x + 2, y + 2, s);
  637.     GRSetColor(Color);
  638.     outtextxy(x, y, s);
  639. }
  640.  
  641. /****************************************************************************
  642. * Routine to get string width in pixel.                        *
  643. ****************************************************************************/
  644. int GRGetTextWidth(char *Str)
  645. {
  646.     return textwidth(Str);
  647. }
  648.  
  649. /****************************************************************************
  650. * Routine to get string height in pixel.                    *
  651. ****************************************************************************/
  652. int GRGetTextHeight(char *Str)
  653. {
  654.     return textheight(Str);
  655. }
  656.  
  657. /****************************************************************************
  658. * Routine to push current font type and text attributes.            *
  659. ****************************************************************************/
  660. void GRPushTextSetting(void)
  661. {
  662.     if (TextSettingStackPtr >= TEXT_SETTING_STACK_SIZE)
  663.     IntrFatalError("Text setting stack overflow.");
  664.  
  665.     gettextsettings(&TextSettingStack[TextSettingStackPtr++]);
  666. }
  667.  
  668. /****************************************************************************
  669. * Routine to pop current font type and text attributes.                *
  670. ****************************************************************************/
  671. void GRPopTextSetting(void)
  672. {
  673.     if (--TextSettingStackPtr < 0)
  674.     IntrFatalError("Text setting stack underflow.");
  675.  
  676.     settextstyle(TextSettingStack[TextSettingStackPtr].font,
  677.              TextSettingStack[TextSettingStackPtr].direction,
  678.          TextSettingStack[TextSettingStackPtr].charsize);
  679.     settextjustify(TextSettingStack[TextSettingStackPtr].horiz,
  680.            TextSettingStack[TextSettingStackPtr].vert);
  681. }
  682.  
  683. /****************************************************************************
  684. * Routine to set color to color within range.                    *
  685. ****************************************************************************/
  686. void GRSetColor(int Color)
  687. {
  688.     if (Color >= GRScreenMaxColors)
  689.     Color = Color % (GRScreenMaxColors - 1) + 1;
  690.     setcolor(Color);
  691. }
  692.  
  693. /****************************************************************************
  694. * Routine to get current active color.                        *
  695. ****************************************************************************/
  696. int GRGetColor(void)
  697. {
  698.     return getcolor();
  699. }
  700.  
  701. /****************************************************************************
  702. * Routine to set one color index RGB values (EGA/VGA only).            *
  703. ****************************************************************************/
  704. void GRSetRGBPalette(int Index, int Red, int Green, int Blue)
  705. {
  706.     setrgbpalette(Index, Red, Green, Blue);
  707. }
  708.  
  709. /****************************************************************************
  710. * Routine to draw the cursor as an arrow.                    *
  711. ****************************************************************************/
  712. void GRPutArrowCursor(int x, int y)
  713. {
  714.     putimage(x, y, CursorImageBuffer, XOR_PUT);
  715. }
  716.  
  717. /*****************************************************************************
  718. *   Routine to clear all the screen.                         *
  719. *****************************************************************************/
  720. void GRClearAllScreen(void)
  721. {
  722.     setviewport(0, 0, GRScreenMaxX, GRScreenMaxY, FALSE);
  723.     cleardevice();
  724. }
  725.  
  726. /*****************************************************************************
  727. *   Routine to clear given rectangle viewport.                     *
  728. *****************************************************************************/
  729. void GRClearViewPort(int x1, int y1, int x2, int y2)
  730. {
  731.     struct viewporttype viewport;
  732.  
  733.     getviewsettings(&viewport);
  734.  
  735.     setviewport(x1, y1, x2, y2, TRUE);
  736.     clearviewport();
  737.  
  738.     setviewport(viewport.left, viewport.top, viewport.right, viewport.bottom,
  739.                                 viewport.clip);
  740. }
  741.  
  742. /*****************************************************************************
  743. *   Routine to set given rectangle viewport.                     *
  744. *****************************************************************************/
  745. void _GRSetViewPort(int x1, int y1, int x2, int y2)
  746. {
  747.     setviewport(x1, y1, x2, y2, TRUE);
  748. }
  749.  
  750. /*****************************************************************************
  751. *   Routine to set given rectangle viewport.                     *
  752. *****************************************************************************/
  753. void _GRSetViewPort2(int x1, int y1, int x2, int y2, IntrBType Clip)
  754. {
  755.     setviewport(x1, y1, x2, y2, Clip);
  756. }
  757.  
  758. /*****************************************************************************
  759. *   Routine to set given rectangle viewport.                     *
  760. *****************************************************************************/
  761. void GRGetViewPort(int *x1, int *y1, int *x2, int *y2)
  762. {
  763.     struct viewporttype viewstruct;
  764.  
  765.     getviewsettings(&viewstruct);
  766.     *x1 = viewstruct.left;
  767.     *x2 = viewstruct.right;
  768.     *y1 = viewstruct.top;
  769.     *y2 = viewstruct.bottom;
  770. }
  771.  
  772. /*****************************************************************************
  773. *   Routine to set given rectangle viewport.                     *
  774. *****************************************************************************/
  775. void GRSetViewPort(int x1, int y1, int x2, int y2)
  776. {
  777.     setviewport(x1, y1, x2, y2, TRUE);
  778.     GRWidth2 = (x2 - x1) / 2;
  779.     GRHeight2 = (y2 - y1) / 2;
  780.     GRMinX = x1;
  781.     GRMinY = y1;
  782. }
  783.  
  784. /*****************************************************************************
  785. *   Routine to push current view port.                         *
  786. *****************************************************************************/
  787. void GRPushViewPort(void)
  788. {
  789.     if (ViewPortStackPtr >= VIEW_PORT_STACK_SIZE)
  790.     IntrFatalError("View port stack overflow.");
  791.  
  792.     getviewsettings(&ViewPortStack[ViewPortStackPtr++]);
  793. }
  794.  
  795. /*****************************************************************************
  796. *   Routine to pop current view port.                         *
  797. *****************************************************************************/
  798. void GRPopViewPort(void)
  799. {
  800.     if (--ViewPortStackPtr < 0)
  801.     IntrFatalError("View port stack underflow.");
  802.  
  803.     setviewport(ViewPortStack[ViewPortStackPtr].left,
  804.         ViewPortStack[ViewPortStackPtr].top,
  805.         ViewPortStack[ViewPortStackPtr].right,
  806.         ViewPortStack[ViewPortStackPtr].bottom,
  807.         ViewPortStack[ViewPortStackPtr].clip);
  808.     GRWidth2 = (ViewPortStack[ViewPortStackPtr].right -
  809.             ViewPortStack[ViewPortStackPtr].left) / 2;
  810.     GRHeight2 = (ViewPortStack[ViewPortStackPtr].bottom -
  811.              ViewPortStack[ViewPortStackPtr].top) / 2;
  812.     GRMinX = ViewPortStack[ViewPortStackPtr].left;
  813.     GRMinY = ViewPortStack[ViewPortStackPtr].top;
  814. }
  815.  
  816. /*****************************************************************************
  817. * Routine to read one line terminated by <Enter> and visualized    on graphic   *
  818. * screen.                                     *
  819. * Full line editing is supported which includes:                 *
  820. * 1. Right and left arrows to move along the line.                 *
  821. * 2. Up and down arrows to circle a history buffer.                 *
  822. * 3. Delete to delete current character.                     *
  823. * 4. Insert to toggle Insert/Overwrite mode.                     *
  824. * 5. Backspace to delete character before current one.                 *
  825. * 6. Home/End to move to beginning/End of string respectively.             *
  826. * 7. Return to accept current line.                         *
  827. * 8. Esc to clear current line.                             *
  828. *                                         *
  829. * Notes:                                     *
  830. * If s is not empty it is used as starting string.                 *
  831. * Line is drawn    starting from position x, y on screen, WindowLen positions.  *
  832. * s buffer is assumed to be of SLen length.                     *
  833. *****************************************************************************/
  834. void GRGetGraphicLine(int WindowID, int x, int y, char s[], int SLen,
  835.               int WindowLen, int ForeColor, int BackColor)
  836. {
  837.     static int i,
  838.     Insert = TRUE;
  839.     int    NextKey, Xstep, xt,
  840.         Len = strlen(s),
  841.         CursorPos = Len,
  842.         FirstVisible = 0,
  843.         FirstTime = TRUE,
  844.     EndOfString = FALSE,
  845.     HistoryBufCrnt = -1;
  846.     char DisplayLine[GR_LINE_LEN];
  847.     struct textsettingstype oldtext;
  848.     _IntrWindowStruct
  849.     *Window = WindowID ? _IntrFindWndwUsingID(WindowID) : NULL;
  850.  
  851.     gettextsettings(&oldtext);
  852.     settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
  853.     settextjustify(LEFT_TEXT, TOP_TEXT);
  854.  
  855.     Xstep = textwidth("M");     /* Get the width in pixels of current font. */
  856.  
  857.     while (!EndOfString) {
  858.     /* Can not display the whole string, so set first visible char:  */
  859.     FirstVisible = CursorPos > WindowLen - 2 ? CursorPos - WindowLen + 2
  860.                          : 0;
  861.     /* Prepare the part of s to be displayed: */
  862.     strncpy(DisplayLine, &s[FirstVisible], GR_LINE_LEN - 1);
  863.     DisplayLine[MIN(WindowLen, GR_LINE_LEN - 1)] = 0;
  864.  
  865.     GRSetColor(ForeColor);
  866.     outtextxy(x, y, DisplayLine);
  867.     xt = x + (CursorPos - FirstVisible) * Xstep;
  868.     if (Insert)
  869.         GRXORRectangle(xt, y + 7, xt + 7, y + 8);
  870.     else
  871.         GRXORRectangle(xt, y, xt + 7, y + 8);
  872.  
  873.     if ((NextKey = GRGetKey()) != KEY_REFRESH || FirstTime) {
  874.         if (Insert)
  875.             GRXORRectangle(xt, y + 7, xt + 7, y + 8);
  876.         else
  877.             GRXORRectangle(xt, y, xt + 7, y + 8);
  878.         GRSetColor(BackColor);     /* Erase the string and the cursor: */
  879.         outtextxy(x, y, DisplayLine);
  880.     }
  881.     FirstTime = FALSE;
  882.  
  883.     switch (NextKey) {
  884.         case KEY_BSPACE:
  885.         if (CursorPos == 0) {
  886.             GRTone(1000, 100);             /* Do some noise... */
  887.             break;
  888.         }
  889.         movmem(&s[CursorPos], &s[CursorPos - 1], Len - CursorPos + 1);
  890.         CursorPos--;
  891.         Len--;
  892.         break;
  893.         case KEY_DELETE:
  894.         if (CursorPos >= Len) {
  895.             GRTone(1000, 100);             /* Do some noise... */
  896.             break;
  897.         }
  898.         movmem(&s[CursorPos + 1], &s[CursorPos], Len - CursorPos);
  899.         Len--;
  900.         break;
  901.         case KEY_RIGHT:
  902.         if (CursorPos >= Len) {
  903.             GRTone(1000, 100);             /* Do some noise... */
  904.             break;
  905.         }
  906.         CursorPos++;
  907.         break;
  908.         case KEY_LEFT:
  909.         if (CursorPos <= 0) {
  910.             GRTone(1000, 100);             /* Do some noise... */
  911.             break;
  912.         }
  913.         CursorPos--;
  914.         break;
  915.         case KEY_UP:
  916.             if (HistoryBufLen == 0) {
  917.             GRTone(1000, 100);             /* Do some noise... */
  918.             break;
  919.             }
  920.  
  921.             if (++HistoryBufCrnt >= HistoryBufLen) HistoryBufCrnt = 0;
  922.  
  923.         strcpy(s, HistoryBuffer[HistoryBufCrnt]);
  924.         CursorPos = Len = strlen(s);
  925.         break;
  926.         case KEY_DOWN:
  927.             if (HistoryBufLen == 0) {
  928.             GRTone(1000, 100);             /* Do some noise... */
  929.             break;
  930.             }
  931.  
  932.             if (--HistoryBufCrnt < 0) HistoryBufCrnt = HistoryBufLen - 1;
  933.  
  934.         strcpy(s, HistoryBuffer[HistoryBufCrnt]);
  935.         CursorPos = Len = strlen(s);
  936.         break;
  937.         case KEY_RETURN:
  938.         EndOfString = TRUE;
  939.         break;
  940.         case KEY_ESC:
  941.         Len = 0;                    /* Clear everything. */
  942.         CursorPos = 0;
  943.         s[0] = 0;
  944.         break;
  945.         case KEY_HOME:
  946.         CursorPos = 0;
  947.         break;
  948.         case KEY_END:
  949.         CursorPos = Len;
  950.         break;
  951.         case KEY_INSERT:
  952.         Insert = !Insert;
  953.         break;
  954.         case KEY_NONE:
  955.             GRTone(1000, 100);             /* Do some noise... */
  956.         GRTone(500, 200);
  957.         break;
  958.         case KEY_REFRESH:              /* Internal event to intr_lib. */
  959.         if (Window != NULL) {
  960.             _GRSetViewPort(Window -> BBox.Xmin, Window -> BBox.Ymin,
  961.                        Window -> BBox.Xmax, Window -> BBox.Ymax);
  962.             x = TEXT_BORDER,
  963.                  y = Window -> BBox.Ymax - Window -> BBox.Ymin -
  964.                        TEXT_BORDER - GRGetTextHeight("M");
  965.         }
  966.         settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
  967.         settextjustify(LEFT_TEXT, TOP_TEXT);
  968.         break;
  969.         default:                      /* Regular ascii char. */
  970.         if (Insert) {
  971.             movmem(&s[CursorPos], &s[CursorPos + 1],
  972.                             Len - CursorPos + 1);
  973.             Len++;
  974.         }
  975.         else if (CursorPos == Len)
  976.             Len++;            /* We are on last character. */
  977.         s[CursorPos++] = NextKey;
  978.         if (CursorPos == Len) s[CursorPos] = 0;
  979.         break;
  980.     }
  981.     if (SLen <= Len - 1) {    /* End of buffer - can not save more info. */
  982.         Len = SLen - 1;
  983.         if (CursorPos > Len) CursorPos = Len;
  984.         GRTone(1000, 100);                 /* Do some noise... */
  985.     }
  986.     }
  987.  
  988.     /* Update the history buffer: */
  989.     for (i = HISTORY_SIZE - 1; i > 0; i--)
  990.     strncpy(HistoryBuffer[i], HistoryBuffer[i - 1], GR_LINE_LEN);
  991.     strncpy(HistoryBuffer[0], s, GR_LINE_LEN);
  992.     HistoryBufLen = MIN(HISTORY_SIZE, HistoryBufLen + 1);
  993.  
  994.     settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
  995.     settextjustify(oldtext.horiz, oldtext.vert);
  996. }
  997.  
  998. /*****************************************************************************
  999. * Sets the function invoked to get a kbd event in GRGetKey.             *
  1000. * NULL will recover the internal default - IntrGetEventWait.             *
  1001. *****************************************************************************/
  1002. void GRSetGetKeyFunc(IntrInt2PtrFunc GetChFunc)
  1003. {
  1004.     if (GetChFunc == NULL)
  1005.     GlblGetChFunc = IntrGetEventWait;
  1006.     else
  1007.         GlblGetChFunc = GetChFunc;
  1008. }
  1009.  
  1010. /*****************************************************************************
  1011. * Get a key from keyboard, and translating operational keys into special     *
  1012. * codes (>255).                                     *
  1013. *****************************************************************************/
  1014. static int GRGetKey(void)
  1015. {
  1016.     int x, y;
  1017.  
  1018.     /* Detach the keyboard from moving the mouse so keyboard can be used to  */
  1019.     /* edit the input line instead.                         */
  1020.     _IntrDetachKbdFromMouse = TRUE;
  1021.     while (GlblGetChFunc(&x, &y) != INTR_EVNT_KEY);
  1022.     _IntrDetachKbdFromMouse = FALSE;
  1023.  
  1024.     if (x >= 256) {
  1025.     switch (x - 256) {    /* Extended code - get the next extended char. */
  1026.         case 72:
  1027.         return KEY_UP;
  1028.         case 80:
  1029.         return KEY_DOWN;
  1030.         case 75:
  1031.         return KEY_LEFT;
  1032.         case 77:
  1033.         return KEY_RIGHT;
  1034.         case 71:
  1035.         return KEY_HOME;
  1036.         case 79:
  1037.         return KEY_END;
  1038.         case 83:
  1039.         return KEY_DELETE;
  1040.         case 82:
  1041.         return KEY_INSERT;
  1042.         case KEY_REFRESH - 256:
  1043.         return KEY_REFRESH;
  1044.     }
  1045.     }
  1046.     else {
  1047.         switch (x) {
  1048.         case 8:
  1049.             return KEY_BSPACE;
  1050.         case 10:
  1051.         case 13:
  1052.             return KEY_RETURN;
  1053.         case 27:
  1054.             return KEY_ESC;
  1055.         default:
  1056.             if (isprint(x)) return x;
  1057.     }
  1058.     }
  1059.  
  1060.     return KEY_NONE;
  1061. }
  1062.  
  1063. /*****************************************************************************
  1064. * Routine to make some sound with given Frequency, Time milliseconds:         *
  1065. *****************************************************************************/
  1066. void GRTone(int Frequency, int Time)
  1067. {
  1068.     sound(Frequency);
  1069.     delay(Time);
  1070.     nosound();
  1071. }
  1072.